//
// Created by void on 24-1-13.
//

#include "Buffer.h"
struct Buffer* bufferInit(int size) {
    struct Buffer* buffer = (struct Buffer*) malloc(sizeof(struct Buffer));
    if(buffer != NULL) {
        buffer->data = (char*) malloc(size);
        buffer->capacity = size;
        buffer->writePos = buffer->readPos = 0;
        memset(buffer->data, 0, size);
    }
    return buffer;
}

void bufferDestory(struct Buffer* buf){
    if(buf != NULL) {
        if(buf->data != NULL) {
            free(buf->data);
        }
    }
    free(buf);
}

void bufferExtendRoom(struct Buffer* buffer, int size) {
    if(bufferWriteableSize(buffer) >= size) {
        return;
    } else if(buffer->readPos + bufferWriteableSize(buffer) >= size) {
        int readable = bufferReadableSize(buffer);
        memcpy(buffer->data, buffer->data + buffer->readPos, readable);
        buffer->readPos = 0;
        buffer->writePos = readable;
    } else {
        void * temp = realloc(buffer->data, buffer->capacity + size);
        if(temp == NULL) {
            return;
        }
        memset(temp + buffer->capacity, 0, size);

        buffer->data = temp;
        buffer->capacity += size;
    }
}

int bufferWriteableSize(struct Buffer* buffer) {
    return buffer->capacity - buffer->writePos;
}

int bufferReadableSize(struct Buffer* buffer) {
    return buffer->writePos - buffer->readPos;
}

int bufferAppendData(struct Buffer* buffer, const char* data, int size) {
    if(buffer == NULL || data == NULL || size < 0) {
        return -1;
    }

    bufferExtendRoom(buffer, size);

    memcpy(buffer->data + buffer->writePos,  data, size);

    buffer->writePos += size;
    return 0;
}

int bufferAppendString(struct Buffer* buffer, const char* data){
    int size = strlen(data);
    return bufferAppendData(buffer, data, size);
}

int bufferSocketRead(struct Buffer* buffer, int fd) {
    struct iovec vec[2];
    int writeable = bufferWriteableSize(buffer);
    vec[0].iov_base = buffer->data + buffer->writePos;
    vec[0].iov_len = writeable;

    char* tmpbuf = (char*) malloc(40960);
    vec[1].iov_base = tmpbuf;
    vec[1].iov_len = 40960;
    int result = readv(fd, vec, 2);
    if(result == -1){
        return -1;
    } else if(result < writeable) {
        buffer->writePos += result;
    } else {
        buffer->writePos = buffer->capacity;
        bufferAppendData(buffer, tmpbuf, result-writeable);
    }
    free(tmpbuf);
    return result;
}

char *bufferFindCRLF(struct Buffer* buffer) {
    char* ptr = memmem(buffer->data+buffer->readPos, bufferReadableSize(buffer), "\r\n", 2);
    return ptr;
}

int bufferSendData(struct Buffer* buffer, int socket) {
    int readable = bufferReadableSize(buffer);
    if(readable > 0) {
        int count = send(socket, buffer->data + buffer->readPos, readable, MSG_NOSIGNAL);
        if(count > 0) {
            buffer->readPos += count;
            usleep(1);
        }
        return count;
    }
    return 0;
}



